import logging#导入Python的标准日志记录模块
from utils.con_to_db import query_data
from math import sqrt

#配置了日志记录模块，使其记录INFO级别及以上的日志消息。

logging.basicConfig(level=logging.INFO)
# 获取推荐表中所有的用户id
"""
1. 创建一个函数
2. 获取推荐表中的所有用户浏览的信息， 根据用户ID进行分类 ，获取所有的用户的ID
3. 对获取到的结果进行变形
"""

class SimpleCache:
    def __init__(self):
        self.cache = {}

    def get(self, key):
        return self.cache.get(key, None)

    def set(self, key, value):
        self.cache[key] = value

# 实例化缓存
cache = SimpleCache()

def get_total_u_id():
    try:
        # SQL查询：选择所有不同的用户ID
        sql = 'SELECT DISTINCT user_id FROM house_recommend'
        result = query_data(sql)
        # 提取查询结果中的用户ID
        total_u_id = [i[0] for i in result]
        return total_u_id
    except Exception as e:
        logging.error(f"Error in get_total_u_id: {e}")
        return []


# 获取每个用户的浏览记录
"""
1. 创建一个函数
2. 通过user_id这个字段过滤出当前用户的所有的浏览历史，从当前的这组数据中 获取house_id  和 score
3. 对获取到的数据进行组装，即{1: {123:4, 234:2} }==>{u_id: {house_id: score, house_id:score.....}}
"""
def get_user_info(user_id):
    try:
        # SQL查询：选择指定用户的所有浏览记录
        sql = f'SELECT user_id, house_id, score FROM house_recommend WHERE user_id = "{user_id}"'
        result = query_data(sql)
        # 初始化字典存储用户浏览信息
        data = {info[0]: {} for info in result}
        for info in result:
            # 填充用户浏览信息
            data[info[0]][info[1]] = info[2]
        return data
    except Exception as e:
        logging.error(f"Error in get_user_info: {e}")
        return {}

# 获取两个用户的相似度
"""
1. 创建一个函数
2. 获取两个用户的 各自的浏览记录
3. 后去两个用户共同的浏览过的房源
4. 使用皮尔逊相关系数的公式获取两个用户的相似度
"""

# 计算两个用户的皮尔逊相似度
def pearson_sim(user1, sim_user):
    # 获取两个用户的浏览记录
    user1_data = get_user_info(user1).get(user1, {})
    user2_data = get_user_info(sim_user).get(sim_user, {})
    # 找到两个用户共同浏览过的房源
    common = [key for key in user1_data if key in user2_data]

    # 如果没有共同浏览过的房源，返回相似度为0
    if len(common) == 0:
        return 0

    n = len(common)
    # 计算共同房源的评分和
    user1_sum = sum([user1_data[hid] for hid in common])
    user2_sum = sum([user2_data[hid] for hid in common])
    # 计算评分的平方和
    pow_sum1 = sum([pow(user1_data[hid], 2) for hid in common])
    pow_sum2 = sum([pow(user2_data[hid], 2) for hid in common])
    # 计算评分的乘积和
    PSum = sum([user1_data[hid] * user2_data[hid] for hid in common])

    # 计算皮尔逊相关系数的分子
    molecule = PSum - (user1_sum * user2_sum / n)
    # 计算皮尔逊相关系数的分母
    denominator = sqrt((pow_sum1 - pow(user1_sum, 2) / n) * (pow_sum2 - pow(user2_sum, 2) / n))

    # 分母为0时，返回相似度为0
    if denominator == 0:
        return 0

    # 返回皮尔逊相关系数
    return molecule / denominator


# 获取相似度在前十名的用户
"""
1. 创建一个函数
2. 获取推荐表中的全部的用户的ID
3. 遍历全部用户的ID获取除自己之外的所有用户的相似度
4. 使用sort()函数来进行降序排序 获取前十名的用户ID
"""

# 获取前十个与指定用户最相似的用户
def top10_similar(UserID):
    # 获取所有用户ID
    total_u_id = get_total_u_id()
    res = []

    for u_id in total_u_id:
        if int(UserID) != u_id:
            # 计算与其他用户的相似度
            similar = pearson_sim(int(UserID), int(u_id))
            if similar > 0:
                res.append((u_id, similar))

    # 按相似度降序排序，返回前十个用户
    res.sort(key=lambda val: val[1], reverse=True)
    return res[:10]


# 获取推荐的房源
"""
1. 创建一个函数
2. 获取相似度最高的用户 通过这个用户 获取他完整的 浏览记录
3. 获取当前这个用户的 完整浏览记录
4. 判断 当前用户中没有  但是在 相似用户中 评价最高的房源
5. 按照 评分 使用sort来进行排序 降序排序 获取前6个
"""

# 获取推荐房源
def recommend(user):
    similar_users = top10_similar(user)
    if not similar_users:
        return None

    # 获取与指定用户最相似的用户
    top_sim_user = similar_users[0][0]
    # 获取相似用户的浏览记录
    items = get_user_info(top_sim_user).get(int(top_sim_user), {})
    # 获取指定用户的浏览记录
    user_data = get_user_info(user).get(int(user), {})

    # 生成推荐列表
    recommendata = [(item, items[item]) for item in items if item not in user_data]
    recommendata.sort(key=lambda val: val[1], reverse=True)
    return recommendata[:6]

if __name__ == '__main__':
    # 获取推荐房源并打印
    recommendations = recommend(1)
    if recommendations:
        for rec in recommendations:
            print(f"House ID: {rec[0]}, Score: {rec[1]}")
    else:
        print("No recommendations found.")